"""
数据库实例管理器

负责管理单个数据库实例，包括该数据库下的所有表、索引、元数据等
"""

import os
import sys
import json
import time
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
from datetime import datetime

# 添加当前目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
if current_dir not in sys.path:
    sys.path.insert(0, current_dir)

from storage_engine import StorageEngine, CachePolicy
from table_schema import Column, ColumnType, TableSchema
from statistics import Logger
from constants import PAGE_SIZE


@dataclass
class DatabaseInfo:
    """数据库信息"""
    name: str
    path: str
    created_time: datetime
    charset: str = "utf8"
    collation: str = "utf8_general_ci"
    status: str = "active"
    
    def to_dict(self) -> Dict:
        """转换为字典格式"""
        data = asdict(self)
        data['created_time'] = self.created_time.isoformat()
        return data
    
    @classmethod
    def from_dict(cls, data: Dict) -> 'DatabaseInfo':
        """从字典创建DatabaseInfo对象"""
        data = data.copy()
        if isinstance(data['created_time'], str):
            data['created_time'] = datetime.fromisoformat(data['created_time'])
        return cls(**data)


class DatabaseInstance:
    """数据库实例"""
    
    def __init__(self, db_name: str, db_path: str, cache_size: int = 100, 
                 cache_policy: CachePolicy = CachePolicy.LRU, 
                 enable_locking: bool = True):
        """
        初始化数据库实例
        
        Args:
            db_name: 数据库名称
            db_path: 数据库文件路径
            cache_size: 缓存大小
            cache_policy: 缓存策略
            enable_locking: 是否启用锁机制
        """
        self.db_name = db_name
        self.db_path = db_path
        self.logger = Logger()
        
        # 确保数据库目录存在
        os.makedirs(db_path, exist_ok=True)
        
        # 数据库信息
        self.db_info = DatabaseInfo(
            name=db_name,
            path=db_path,
            created_time=datetime.now()
        )
        
        # 创建存储引擎（每个数据库有独立的存储引擎）
        storage_path = os.path.join(db_path, f"{db_name}.db")
        self.storage_engine = StorageEngine(
            db_path=storage_path,
            cache_size=cache_size,
            cache_policy=cache_policy,
            enable_locking=enable_locking,
            enable_readahead=True  # 默认启用预读
        )
        
        # 表管理
        self.tables: Dict[str, TableSchema] = {}
        
        # 加载数据库元数据
        self._load_database_metadata()
        
        self.logger.info("DATABASE", 0, f"Database instance '{db_name}' initialized")
    
    def _load_database_metadata(self):
        """加载数据库元数据"""
        metadata_file = os.path.join(self.db_path, "database.meta")
        
        try:
            if os.path.exists(metadata_file):
                with open(metadata_file, 'r', encoding='utf-8') as f:
                    metadata = json.load(f)
                
                # 加载数据库信息
                if 'database_info' in metadata:
                    self.db_info = DatabaseInfo.from_dict(metadata['database_info'])
                
                # 加载表信息
                if 'tables' in metadata:
                    for table_name, table_data in metadata['tables'].items():
                        try:
                            schema = TableSchema.from_dict(table_data)
                            self.tables[table_name] = schema
                        except Exception as e:
                            self.logger.error("LOAD_META", 0, f"Failed to load table {table_name}: {e}")
                
                self.logger.info("LOAD_META", 0, f"Loaded metadata for database '{self.db_name}'")
            else:
                # 新数据库，保存初始元数据
                self._save_database_metadata()
                
        except Exception as e:
            self.logger.error("LOAD_META", 0, f"Failed to load database metadata: {e}")
    
    def _save_database_metadata(self):
        """保存数据库元数据"""
        metadata_file = os.path.join(self.db_path, "database.meta")
        
        try:
            metadata = {
                'database_info': self.db_info.to_dict(),
                'tables': {
                    name: schema.to_dict() 
                    for name, schema in self.tables.items()
                },
                'version': '1.0',
                'last_updated': datetime.now().isoformat()
            }
            
            with open(metadata_file, 'w', encoding='utf-8') as f:
                json.dump(metadata, f, indent=2, ensure_ascii=False)
            
            self.logger.info("SAVE_META", 0, f"Saved metadata for database '{self.db_name}'")
            
        except Exception as e:
            self.logger.error("SAVE_META", 0, f"Failed to save database metadata: {e}")
    
    def create_table(self, table_name: str, columns: List[Column]) -> bool:
        """
        在该数据库中创建表
        
        Args:
            table_name: 表名
            columns: 列定义列表
            
        Returns:
            bool: 创建是否成功
        """
        if table_name in self.tables:
            self.logger.warn("CREATE_TABLE", 0, f"Table '{table_name}' already exists in database '{self.db_name}'")
            return False
        
        try:
            # 使用存储引擎创建表
            success = self.storage_engine.create_table(table_name, columns)
            
            if success:
                # 添加到表管理
                schema = TableSchema(table_name, columns)
                self.tables[table_name] = schema
                
                # 保存元数据
                self._save_database_metadata()
                
                self.logger.info("CREATE_TABLE", 0, f"Created table '{table_name}' in database '{self.db_name}'")
                return True
            else:
                self.logger.error("CREATE_TABLE", 0, f"Failed to create table '{table_name}' in storage engine")
                return False
                
        except Exception as e:
            self.logger.error("CREATE_TABLE", 0, f"Failed to create table '{table_name}': {e}")
            return False
    
    def drop_table(self, table_name: str) -> bool:
        """
        删除表
        
        Args:
            table_name: 表名
            
        Returns:
            bool: 删除是否成功
        """
        if table_name not in self.tables:
            self.logger.warn("DROP_TABLE", 0, f"Table '{table_name}' does not exist in database '{self.db_name}'")
            return False
        
        try:
            # 使用存储引擎删除表
            success = self.storage_engine.drop_table(table_name)
            
            if success:
                # 从表管理中移除
                del self.tables[table_name]
                
                # 保存元数据
                self._save_database_metadata()
                
                self.logger.info("DROP_TABLE", 0, f"Dropped table '{table_name}' from database '{self.db_name}'")
                return True
            else:
                self.logger.error("DROP_TABLE", 0, f"Failed to drop table '{table_name}' from storage engine")
                return False
                
        except Exception as e:
            self.logger.error("DROP_TABLE", 0, f"Failed to drop table '{table_name}': {e}")
            return False
    
    def insert_record(self, table_name: str, record_data: Dict[str, Any]) -> bool:
        """
        插入记录
        
        Args:
            table_name: 表名
            record_data: 记录数据
            
        Returns:
            bool: 插入是否成功
        """
        if table_name not in self.tables:
            self.logger.error("INSERT", 0, f"Table '{table_name}' does not exist in database '{self.db_name}'")
            return False
        
        # 获取当前事务ID（如果有）
        transaction_id = getattr(self, '_current_transaction_id', None)
        return self.storage_engine.insert_record(table_name, record_data, transaction_id=transaction_id)
    
    def select_records(self, table_name: str, condition=None) -> List[Dict[str, Any]]:
        """
        查询记录
        
        Args:
            table_name: 表名
            condition: 查询条件
            
        Returns:
            List[Dict]: 查询结果
        """
        if table_name not in self.tables:
            self.logger.error("SELECT", 0, f"Table '{table_name}' does not exist in database '{self.db_name}'")
            return []
        
        return self.storage_engine.select_records(table_name, condition)
    
    def update_records(self, table_name: str, condition: Dict, updates: Dict) -> int:
        """
        更新记录
        
        Args:
            table_name: 表名
            condition: 更新条件
            updates: 更新内容
            
        Returns:
            int: 更新的记录数量
        """
        if table_name not in self.tables:
            self.logger.error("UPDATE", 0, f"Table '{table_name}' does not exist in database '{self.db_name}'")
            return 0
        
        # 获取当前事务ID（如果有）
        transaction_id = getattr(self, '_current_transaction_id', None)
        return self.storage_engine.update_records(table_name, condition, updates, transaction_id=transaction_id)
    
    def delete_records(self, table_name: str, condition: Dict) -> int:
        """
        删除记录
        
        Args:
            table_name: 表名
            condition: 删除条件
            
        Returns:
            int: 删除的记录数量
        """
        if table_name not in self.tables:
            self.logger.error("DELETE", 0, f"Table '{table_name}' does not exist in database '{self.db_name}'")
            return 0
        
        # 获取当前事务ID（如果有）
        transaction_id = getattr(self, '_current_transaction_id', None)
        return self.storage_engine.delete_records(table_name, condition, transaction_id=transaction_id)
    
    def list_tables(self) -> List[str]:
        """获取数据库中的所有表名"""
        return list(self.tables.keys())
    
    def get_table_schema(self, table_name: str) -> Optional[TableSchema]:
        """获取表结构"""
        return self.tables.get(table_name)
    
    def get_database_info(self) -> DatabaseInfo:
        """获取数据库信息"""
        return self.db_info
    
    def get_database_stats(self) -> Dict[str, Any]:
        """获取数据库统计信息"""
        storage_stats = self.storage_engine.get_storage_stats()
        cache_stats = self.storage_engine.get_cache_stats()
        
        return {
            'database_name': self.db_name,
            'database_path': self.db_path,
            'table_count': len(self.tables),
            'tables': list(self.tables.keys()),
            'created_time': self.db_info.created_time.isoformat(),
            'status': self.db_info.status,
            'storage_stats': {
                'total_pages': storage_stats.total_pages,
                'pages_allocated': storage_stats.pages_allocated,
                'pages_read': storage_stats.pages_read,
                'pages_written': storage_stats.pages_written
            },
            'cache_stats': {
                'cache_size': cache_stats.cache_size,
                'cache_hits': cache_stats.cache_hits,
                'cache_misses': cache_stats.cache_misses,
                'hit_rate': cache_stats.hit_rate
            }
        }
    
    def get_readahead_statistics(self) -> dict:
        """获取预读统计信息"""
        try:
            stats = self.storage_engine.get_readahead_statistics()
            stats['database_name'] = self.db_name
            return stats
        except Exception as e:
            self.logger.error("STATS", 0, f"Failed to get readahead statistics: {e}")
            return {'database_name': self.db_name, 'error': str(e)}
    
    def configure_readahead(self, **kwargs):
        """配置预读参数"""
        try:
            self.storage_engine.configure_readahead(**kwargs)
            self.logger.info("CONFIG", 0, f"Readahead configuration updated for database '{self.db_name}': {kwargs}")
        except Exception as e:
            self.logger.error("CONFIG", 0, f"Failed to configure readahead: {e}")
    
    def print_readahead_status(self):
        """打印预读状态"""
        print(f"\n=== 数据库 '{self.db_name}' 预读状态 ===")
        try:
            self.storage_engine.print_readahead_status()
        except Exception as e:
            print(f"获取预读状态失败: {e}")
    
    def close(self):
        """关闭数据库实例"""
        try:
            # 保存元数据
            self._save_database_metadata()
            
            # 关闭存储引擎
            self.storage_engine.close()
            
            self.logger.info("CLOSE", 0, f"Database instance '{self.db_name}' closed")
            
        except Exception as e:
            self.logger.error("CLOSE", 0, f"Error closing database instance '{self.db_name}': {e}")
    
    # ==================== WAL代理方法 ====================
    
    def set_current_transaction(self, transaction_id: str):
        """设置当前事务ID"""
        self._current_transaction_id = transaction_id
    
    def clear_current_transaction(self):
        """清除当前事务ID"""
        self._current_transaction_id = None
    
    def _ensure_wal_initialized(self):
        """代理到存储引擎的WAL初始化"""
        if hasattr(self.storage_engine, '_ensure_wal_initialized'):
            return self.storage_engine._ensure_wal_initialized()
        return False
    
    @property
    def wal_manager(self):
        """获取WAL管理器"""
        if hasattr(self.storage_engine, 'wal_manager'):
            return self.storage_engine.wal_manager
        return None
    
    def __enter__(self):
        """支持with语句"""
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """支持with语句"""
        self.close()
